package com.alibaba.citrus.ots.sales.plan.repository;

import com.alibaba.acm.shaded.com.alibaba.metrics.StringUtils;
import com.alibaba.citrus.ots.common.annotation.RepositoryInvoker;
import com.alibaba.citrus.ots.common.exception.RepositoryException;
import com.alibaba.citrus.ots.sales.plan.dto.api.request.MonthContractAndRollingCountResponse;
import com.alibaba.citrus.ots.sales.plan.dto.api.request.*;
import com.alibaba.citrus.ots.sales.plan.model.enums.ContractDataSourceEnum;
import com.alibaba.citrus.ots.sales.plan.model.enums.ContractStatDimensionEnum;
import com.alibaba.citrus.ots.sales.plan.repository.request.QueryCountByYearRequest;
import com.alibaba.citrus.ots.sales.plan.repository.request.SearchContractRepoReq;
import com.alibaba.citrus.ots.sales.plan.sdo.ContractSDO;
import com.alibaba.cz.base.tool.log.Log;
import com.alibaba.cz.base.tool.page.PageResult;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.lattice2.epoch.sdk.model.Result;
import com.epoch.app.bcots.bosalesplancontractinfoindex.dto.BatchQueryRequest;
import com.epoch.app.bcots.bosalesplancontractinfoindex.dto.BatchQueryResponse;
import com.epoch.app.bcots.bosalesplancontractinfoindex.service.BoSalesPlanContractInfoIndexService;
import com.epoch.app.bcots.model.dto.*;
import com.epoch.app.bcots.sales_plan.contract.dto.PageQueryContractListRequest;
import com.epoch.app.bcots.sales_plan.contract.dto.PageQueryContractListResponse;
import com.epoch.app.bcots.sales_plan.contract.dto.*;
import com.epoch.app.bcots.sales_plan.contract.model.Contract;
import com.epoch.app.bcots.sales_plan.contract.service.ContractService;
import com.epoch.app.bcots.sales_plan.departmentcontractredline.dto.BatchQueryDepartmentContractRequest;
import com.epoch.app.bcots.sales_plan.departmentcontractredline.dto.BatchQueryDepartmentContractResponse;
import com.epoch.app.bcots.sales_plan.departmentcontractredline.model.DepartmentContractRedLine;
import com.epoch.app.bcots.sales_plan.departmentcontractredline.service.DepartmentContractRedLineService;
import com.epoch.app.bcots.service.BaseDataService;
import com.epoch.app.otsplatformenhance.api.customeraddressquery.service.CustomerAddressQueryService;
import com.epoch.app.otsplatformenhance.api.customerquery.service.CustomerQueryService;
import com.epoch.app.otsplatformenhance.dto.request.CustomerAddressBatchRequest;
import com.epoch.app.otsplatformenhance.dto.request.CustomerBatchRequest;
import com.epoch.app.otsplatformenhance.sdo.CustomerAddressSDO;
import com.epoch.app.otsplatformenhance.sdo.CustomerSDO;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.text.DecimalFormat;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

/**
 * @author wangyibing
 */
@Component
public class ContractRepositoryImpl implements ContractRepository {
    private static final Log log = Log.getLogger(ContractRepositoryImpl.class);
    @Resource
    private ContractService contractService;
    @Resource
    private BoSalesPlanContractInfoIndexService boSalesPlanContractInfoIndexService;

    private static final int ZERO = 0;

    private static final int SIZE = 100;

    private static final int LIMIT = 1000;

//    @Resource
//    private OrganizationRepository organizationRepository;
//
//    @Resource
//    private ScItemRepository scItemRepository;
//
//    @Resource
//    private CustomerRepository customerRepository;
//
//    @Resource
//    private CustomerAddressRepository customerAddressRepository;

    @Override
    @RepositoryInvoker(printLog = true)
    public String createContract(CreateContractRequest createContractRequest) {
        Contract createRequest = contractCreateRequestConverter(createContractRequest);
        CreateContractResponse contract = contractService.createContract(createRequest);
        return contract.getLastInsertId();
    }

    @Resource
    private BaseDataService baseDataService;
    @Resource
    private CustomerQueryService customerQueryService;
    @Resource
    private CustomerAddressQueryService customerAddressQueryService;

    @Resource
    private DepartmentContractRedLineService departmentContractRedLineService;

    @Override
    @RepositoryInvoker(printLog = true)
    public PageResult<List<ContractSDO>> pageQuery(PageQueryContractRequest pageQueryContractRequest, Boolean isFull) {
        if (StringUtils.isNotBlank(pageQueryContractRequest.getOutrId())) {
            //根据外部编码获得scItemId
            SearchScItemRequest searchScItemRequest = new SearchScItemRequest();
            Map searchReqDTO = new HashMap();
            searchReqDTO.put("outerId", pageQueryContractRequest.getOutrId());
            searchScItemRequest.setSearchReqDTO(searchReqDTO);
            Result<List<ScItemSDO>> listResult = baseDataService.searchScItem(searchScItemRequest);
            if (listResult.getResult().isEmpty()){
                throw new RepositoryException("OTS-02-001-00-15-0011");
            }
            List<String> scItemIdList = listResult.getResult().stream().map(ScItemSDO::getScItemId).filter(StringUtils::isNotBlank).collect(Collectors.toList());
            if (CollectionUtils.isNotEmpty(scItemIdList)) {
                pageQueryContractRequest.setScItemIds(scItemIdList);
                if (StringUtils.isNotBlank(pageQueryContractRequest.getScItemId())) {
                    if (scItemIdList.contains(pageQueryContractRequest.getScItemId())) {
                        pageQueryContractRequest.setScItemIds(Lists.newArrayList(pageQueryContractRequest.getScItemId()));
                    } else {
                        throw new RepositoryException("OTS-02-001-00-15-0010");
                    }
                }
            } else {
                throw new RepositoryException("OTS-02-001-00-15-0011");
            }
//            if (StringUtils.isNotBlank(pageQueryContractRequest.getScItemId())){
//                if (scItemSDO.getScItemId().equals(pageQueryContractRequest.getScItemId())){
//                    pageQueryContractRequest.setScItemId(scItemSDO.getScItemId());
//                }else {
//                    throw new RepositoryException("OTS-02-001-00-15-0010");
//                }
//            }else {
//                pageQueryContractRequest.setScItemId(scItemSDO.getScItemId());
//            }

        }
        if (StringUtils.isNotBlank(pageQueryContractRequest.getScItemId())) {
            if (CollectionUtils.isEmpty(pageQueryContractRequest.getScItemIds())) {
                pageQueryContractRequest.setScItemIds(Lists.newArrayList(pageQueryContractRequest.getScItemId()));
            }
        }

        if (StringUtils.isNotBlank(pageQueryContractRequest.getCustomerAddress())) {
            if (CollectionUtils.isNotEmpty(pageQueryContractRequest.getCustomerAddresses())) {
                pageQueryContractRequest.getCustomerAddresses().add(pageQueryContractRequest.getCustomerAddress());
            } else {
                pageQueryContractRequest.setCustomerAddresses(Lists.newArrayList(pageQueryContractRequest.getCustomerAddress()));
            }
        }
        PageQueryContractListRequest loadListRequest = contractQueryRequestConverter(pageQueryContractRequest);
        PageQueryContractListResponse pageQueryContractListResponse = contractService.pageQueryContractList(loadListRequest);
        if (pageQueryContractListResponse == null || pageQueryContractListResponse.getTotal() == 0) {
            return PageResult.of(Lists.newArrayList(), 0);
        }
        List<Contract> contractList = pageQueryContractListResponse.getResult();
        Map<String, com.epoch.app.bcots.model.dto.OrganizationSDO> organizationMap = Maps.newHashMap();
        Map<String, com.epoch.app.bcots.model.dto.ScItemSDO> scItemMap = Maps.newHashMap();
        Map<String, CustomerSDO> customerMap = Maps.newHashMap();
        Map<String, CustomerAddressSDO> customerAddressMap = Maps.newHashMap();
        if (isFull) {
            Set<String> organizationIdList = Sets.newHashSet();
            Set<String> scItemIdList = Sets.newHashSet();
            Set<String> customerCodeList = Sets.newHashSet();
            Set<String> customerAddressCodeList = Sets.newHashSet();
            for (Contract c : contractList) {
                if (!Objects.isNull(c.getOrgBusinessUnitCode())) {
                    organizationIdList.add(c.getOrgBusinessUnitCode());
                }
                if (!Objects.isNull(c.getOrgSalesOrganizationCode())) {
                    organizationIdList.add(c.getOrgSalesOrganizationCode());
                }
                if (!Objects.isNull(c.getOrgSalesChannelCode())) {
                    organizationIdList.add(c.getOrgSalesChannelCode());
                }
                if (!Objects.isNull(c.getOrgSalesDepartmentCode())) {
                    organizationIdList.add(c.getOrgSalesDepartmentCode());
                }
                if (!Objects.isNull(c.getScItemId())) {
                    scItemIdList.add(c.getScItemId());
                }
                if (!Objects.isNull(c.getCustomerCode())) {
                    customerCodeList.add(c.getCustomerCode());
                }
                if (!Objects.isNull(c.getCustomerAddress())) {
                    customerAddressCodeList.add(c.getCustomerAddress());
                }
            }
            if (CollectionUtils.isNotEmpty(organizationIdList)){
                BaselineGetOrganizationByIds2Request byIds2Request = new BaselineGetOrganizationByIds2Request();
                byIds2Request.setIds(Lists.newArrayList(organizationIdList));
                BaselineGetOrganizationByIds2Response byIds2Response = baseDataService.baselineGetOrganizationByIds2(byIds2Request);
                if (byIds2Response != null && CollectionUtils.isNotEmpty(byIds2Response.getResult())){
                    organizationMap = byIds2Response.getResult().stream().collect(Collectors.toMap(com.epoch.app.bcots.model.dto.OrganizationSDO::getId,o->o));
                }
            }
            if (CollectionUtils.isNotEmpty(scItemIdList)){
                SearchScItemRequest searchScItemRequest = new SearchScItemRequest();
                JSONObject searchReqDTO = new JSONObject();
                searchReqDTO.put("scItemIds",scItemIdList);
                searchReqDTO.put("statusList", Lists.newArrayList(1,-1));
                searchScItemRequest.setSearchReqDTO(searchReqDTO);
                searchScItemRequest.setPageSize(scItemIdList.size());
                Result<List<com.epoch.app.bcots.model.dto.ScItemSDO>> scItem = baseDataService.searchScItem(searchScItemRequest);
                if (scItem != null && CollectionUtils.isNotEmpty(scItem.getResult())){
                    scItemMap = scItem.getResult().stream().collect(Collectors.toMap(com.epoch.app.bcots.model.dto.ScItemSDO::getScItemId,s->s));
                }
            }
            if (CollectionUtils.isNotEmpty(customerAddressCodeList)){
                CustomerAddressBatchRequest batchRequest = new CustomerAddressBatchRequest();
                batchRequest.setAddressCodes(Lists.newArrayList(customerAddressCodeList));
//                batchRequest.setStatus(1);
                Result<List<CustomerAddressSDO>> customerAddress = customerAddressQueryService.batchQueryCustomerAddress(batchRequest);
                if (customerAddress != null && CollectionUtils.isNotEmpty(customerAddress.getResult())){
                    customerAddressMap = customerAddress.getResult().stream().collect(Collectors.toMap(CustomerAddressSDO::getAddressCode,a->a,(a,b)->a));
                }
            }
            if (CollectionUtils.isNotEmpty(customerCodeList)){
                CustomerBatchRequest customerBatchRequest = new CustomerBatchRequest();
                customerBatchRequest.setCodes(Lists.newArrayList(customerCodeList));
                Result<List<CustomerSDO>> listResult = customerQueryService.batchQueryCustomer(customerBatchRequest);
                if (listResult != null && CollectionUtils.isNotEmpty(listResult.getResult())){
                    customerMap = listResult.getResult().stream().collect(Collectors.toMap(CustomerSDO::getCode,c->c));
                }
            }
        }
        List<ContractSDO> result = Lists.newArrayList();
        for (Contract c : contractList) {
            ContractSDO contractSDO = new ContractSDO();
            BeanUtils.copyProperties(c, contractSDO);
            CustomerSDO customerSDO = customerMap.get(c.getCustomerCode());
            contractSDO.setCustomerName(Objects.isNull(customerSDO) ? null : customerSDO.getName());
            CustomerAddressSDO addressSDO = customerAddressMap.get(c.getCustomerAddress());
            contractSDO.setCustomerAddressName(Objects.isNull(addressSDO) ? null : addressSDO.getAddressName());
            com.epoch.app.bcots.model.dto.ScItemSDO scItemSDO = scItemMap.get(c.getScItemId());
            contractSDO.setScItemName(Objects.isNull(scItemSDO) ? null : scItemSDO.getTitle());
            contractSDO.setScItemCode(Objects.isNull(scItemSDO) ? null : scItemSDO.getOuterId());
            com.epoch.app.bcots.model.dto.OrganizationSDO businessUnit = organizationMap.get(c.getOrgBusinessUnitCode());
            contractSDO.setOrgBusinessUnitName(Objects.isNull(businessUnit) ? null : businessUnit.getName());
            contractSDO.setOrgBusinessUnitOuterCode(Objects.isNull(businessUnit) ? null : businessUnit.getCode());
            com.epoch.app.bcots.model.dto.OrganizationSDO organizationSDO = organizationMap.get(c.getOrgSalesOrganizationCode());
            contractSDO.setOrgSalesOrganizationName(Objects.isNull(organizationSDO) ? null : organizationSDO.getName());
            com.epoch.app.bcots.model.dto.OrganizationSDO orgSalesChannel = organizationMap.get(c.getOrgSalesChannelCode());
            contractSDO.setOrgSalesChannelName(Objects.isNull(orgSalesChannel) ? null : orgSalesChannel.getName());
            contractSDO.setOrgSalesChannelOuterCode(Objects.isNull(orgSalesChannel) ? null : orgSalesChannel.getCode());
            com.epoch.app.bcots.model.dto.OrganizationSDO orgSalesDepartment = organizationMap.get(c.getOrgSalesDepartmentCode());
            contractSDO.setOrgSalesDepartmentName(Objects.isNull(orgSalesDepartment) ? null : orgSalesDepartment.getName());
            contractSDO.setOrgSalesDepartmentOuterCode(Objects.isNull(orgSalesDepartment) ? null : orgSalesDepartment.getCode());
//            contractSDO.setGmt_create(c.getGmtCreate());
//            contractSDO.setGmt_modified(c.getGmtModified());
            contractSDO.setGmt_create(c.getGmt_create());
            contractSDO.setGmt_modified(c.getGmt_modified());

            setAmountString(contractSDO);


            result.add(contractSDO);
        }

//        List<ContractSDO> contractSDOS = contractList.stream().map(item -> {
//            ContractSDO contractSDO = new ContractSDO();
//            BeanUtils.copyProperties(item, contractSDO);
//            fillOrganizationAndScItemInfo(contractSDO);
//            fillCustomerInfo(contractSDO);
//            return contractSDO;
//        }).collect(Collectors.toList());
        return PageResult.of(result, pageQueryContractListResponse.getTotal());
    }

    private void setAmountString(ContractSDO contractSDO) {
        contractSDO.setAnnualAmountString(getDoubleString(contractSDO.getAnnualAmount()));
        contractSDO.setJanAmountString(getDoubleString(contractSDO.getJanAmount()));
        contractSDO.setFebAmountString(getDoubleString(contractSDO.getFebAmount()));
        contractSDO.setMarAmountString(getDoubleString(contractSDO.getMarAmount()));
        contractSDO.setAprAmountString(getDoubleString(contractSDO.getAprAmount()));
        contractSDO.setMayAmountString(getDoubleString(contractSDO.getMayAmount()));
        contractSDO.setJuneAmountString(getDoubleString(contractSDO.getJuneAmount()));
        contractSDO.setJulyAmountString(getDoubleString(contractSDO.getJulyAmount()));
        contractSDO.setAugAmountString(getDoubleString(contractSDO.getAugAmount()));
        contractSDO.setSeptAmountString(getDoubleString(contractSDO.getSeptAmount()));
        contractSDO.setOctAmountString(getDoubleString(contractSDO.getOctAmount()));
        contractSDO.setNovAmountString(getDoubleString(contractSDO.getNovAmount()));
        contractSDO.setDecAmountString(getDoubleString(contractSDO.getDecAmount()));

        contractSDO.setAnnualAfterDiscountString(getDoubleString(contractSDO.getAnnualAfterDiscount()));
        contractSDO.setJanAfterDiscountString(getDoubleString(contractSDO.getJanAfterDiscount()));
        contractSDO.setFebAfterDiscountString(getDoubleString(contractSDO.getFebAfterDiscount()));
        contractSDO.setMarAfterDiscountString(getDoubleString(contractSDO.getMarAfterDiscount()));
        contractSDO.setAprAfterDiscountString(getDoubleString(contractSDO.getAprAfterDiscount()));
        contractSDO.setMayAfterDiscountString(getDoubleString(contractSDO.getMayAfterDiscount()));
        contractSDO.setJuneAfterDiscountString(getDoubleString(contractSDO.getJuneAfterDiscount()));
        contractSDO.setJulyAfterDiscountString(getDoubleString(contractSDO.getJulyAfterDiscount()));
        contractSDO.setAugAfterDiscountString(getDoubleString(contractSDO.getAugAfterDiscount()));
        contractSDO.setSeptAfterDiscountString(getDoubleString(contractSDO.getSeptAfterDiscount()));
        contractSDO.setOctAfterDiscountString(getDoubleString(contractSDO.getOctAfterDiscount()));
        contractSDO.setNovAfterDiscountString(getDoubleString(contractSDO.getNovAfterDiscount()));
        contractSDO.setDecAfterDiscountString(getDoubleString(contractSDO.getDecAfterDiscount()));

        contractSDO.setAnnualTaxIncludedBeforeTaxString(getDoubleString(contractSDO.getAnnualTaxIncludedBeforeTax()));
        contractSDO.setJanTaxIncludedBeforeTaxString(getDoubleString(contractSDO.getJanTaxIncludedBeforeTax()));
        contractSDO.setFebTaxIncludedBeforeTaxString(getDoubleString(contractSDO.getFebTaxIncludedBeforeTax()));
        contractSDO.setMarTaxIncludedBeforeTaxString(getDoubleString(contractSDO.getMarTaxIncludedBeforeTax()));
        contractSDO.setAprTaxIncludedBeforeTaxString(getDoubleString(contractSDO.getAprTaxIncludedBeforeTax()));
        contractSDO.setMayTaxIncludedBeforeTaxString(getDoubleString(contractSDO.getMayTaxIncludedBeforeTax()));
        contractSDO.setJuneTaxIncludedBeforeTaxString(getDoubleString(contractSDO.getJuneTaxIncludedBeforeTax()));
        contractSDO.setJulyTaxIncludedBeforeTaxString(getDoubleString(contractSDO.getJulyTaxIncludedBeforeTax()));
        contractSDO.setAugTaxIncludedBeforeTaxString(getDoubleString(contractSDO.getAugTaxIncludedBeforeTax()));
        contractSDO.setSeptTaxIncludedBeforeTaxString(getDoubleString(contractSDO.getSeptTaxIncludedBeforeTax()));
        contractSDO.setOctTaxIncludedBeforeTaxString(getDoubleString(contractSDO.getOctTaxIncludedBeforeTax()));
        contractSDO.setNovTaxIncludedBeforeTaxString(getDoubleString(contractSDO.getNovTaxIncludedBeforeTax()));
        contractSDO.setDecTaxIncludedBeforeTaxString(getDoubleString(contractSDO.getDecTaxIncludedBeforeTax()));
    }

    @Override
    @RepositoryInvoker(printLog = true)
    public ContractSDO queryContractById(QueryContractRequest queryContractRequest) {
        LoadContractRequest loadRequest = contractRequestConverter(queryContractRequest);
        Contract contract = contractService.loadContract(loadRequest);
        return contractResponseConverter(contract);
    }

    private ContractSDO contractResponseConverter(Contract loadResponse) {
        ContractSDO contractSDO = new ContractSDO();
        BeanUtils.copyProperties(loadResponse, contractSDO);
        return contractSDO;
    }


    @Override
    @RepositoryInvoker(printLog = true)
    public Integer editContract(ContractSDO contractSDO) {
        Contract contract = contractUpdateRequestConverter(contractSDO);
        UpdateContractResponse updateContractResponse = contractService.updateContract(contract);
        return updateContractResponse.getCount();
    }

    @Override
    @RepositoryInvoker(printLog = true)
    public String save(ContractSDO contractSDO) {
        Contract contract = contractCreateConverter(contractSDO);
        CreateContractResponse response = contractService.createContract(contract);
        return response.getLastInsertId();
    }

    @Override
    @RepositoryInvoker(printLog = true)
    public List<MonthContractAndRollingCountResponse> queryQuantityListByAddressAndScItem(QueryContractByCustomerDimensionRequest customerDimensionRequest) {
        BatchQueryByCustomerAddressAndScItemRequest addressAndScItemRequest = BatchQueryByCustomerAddressAndScItemRequest.builder().build();
        BeanUtils.copyProperties(customerDimensionRequest, addressAndScItemRequest);
        if (CollectionUtils.isNotEmpty(customerDimensionRequest.getCustomerAddressesIds())){
            addressAndScItemRequest.setCustomerAddressIds(customerDimensionRequest.getCustomerAddressesIds());
        }
        BatchQueryByCustomerAddressAndScItemResponse contractResponse = contractService.batchQueryByCustomerAddressAndScItem(addressAndScItemRequest);
        if (contractResponse != null && CollectionUtils.isEmpty(contractResponse.getResult())) {
            return Lists.newArrayList();
        }

        return contractResponse.getResult().stream().map(contract -> {
            Map<String, Integer> contractCountToMap = converterContractCountToMap(contract);
            Map<String, Long> contractAmountToMap = converterContractAmountToMap(contract);
            Map<String, Long> contractBeforeAmountToMap = converterContractBeforeAmountToMap(contract);
            MonthContractAndRollingCountResponse response = new MonthContractAndRollingCountResponse();
            BeanUtils.copyProperties(contract, response);
            response.setPlanMonth(customerDimensionRequest.getPlanMonth());
            fillContractCountAndAmount(contractCountToMap, contractAmountToMap, contractBeforeAmountToMap, response, customerDimensionRequest);
            return response;
        }).collect(Collectors.toList());
    }

    @Override
    @RepositoryInvoker(printLog = true)
    public Integer batchCreateContract(List<ContractSDO> createContractRequestList) {
        List<Contract> contractList = createContractRequestList.stream().map(item -> {
            Contract contract = new Contract();
            BeanUtils.copyProperties(item, contract);
            return contract;
        }).collect(Collectors.toList());
        BatchCreateContractRequest batchCreateContractRequest = BatchCreateContractRequest.builder().createContractRequestList(contractList).build();
        BatchCreateContractResponse batchCreateContractResponse = contractService.batchCreateContract(batchCreateContractRequest);
        return batchCreateContractResponse.getCount();
    }

    @Override
    @RepositoryInvoker(printLog = true)
    public List<ContractSDO> queryGroupByCompanyScItem(String contractYear) {

        LoadListGroupByCompanyScItemRequest request = LoadListGroupByCompanyScItemRequest.builder().start(0).limit(LIMIT).contractYear(contractYear).build();
        LoadListGroupByCompanyScItemResponse response = contractService.loadListGroupByCompanyScItem(request);
        List<Contract> result = response.getResult();
        if (CollectionUtils.isEmpty(result)) {
            return Lists.newArrayList();
        }
        List<Contract> groupList = Lists.newArrayList();
        int totalPage = getTotalPage(response.getTotal(), LIMIT);
        for (int i = 1; i <= totalPage; i++) {
            LoadListGroupByCompanyScItemRequest req = LoadListGroupByCompanyScItemRequest.builder().contractYear(contractYear).start((i - 1) * LIMIT).limit(LIMIT).build();
            LoadListGroupByCompanyScItemResponse res = contractService.loadListGroupByCompanyScItem(req);
            List<Contract> contracts = res.getResult();
            if (CollectionUtils.isEmpty(contracts)) {
                continue;
            }
            groupList.addAll(contracts);
        }
        return groupList.stream().map(c -> {
            ContractSDO contractSDO = new ContractSDO();
            BeanUtils.copyProperties(c, contractSDO);
            contractSDO.setId(null);
            contractSDO.setDataSource(ContractDataSourceEnum.CUSTOMER.getCode());
            contractSDO.setType(ContractStatDimensionEnum.COMPANY_SC_ITEM.getCode());
            return contractSDO;
        }).collect(Collectors.toList());
    }


    @Override
    @RepositoryInvoker(printLog = true)
    public List<ContractSDO> queryGroupByDepartmentScItem(String contractYear) {

        LoadListGroupByDepartmentScItemRequest request = LoadListGroupByDepartmentScItemRequest.builder().start(0).limit(LIMIT).contractYear(contractYear).build();
        LoadListGroupByDepartmentScItemResponse loadListGroupByDepartmentScItemResponse = contractService.loadListGroupByDepartmentScItem(request);
        List<Contract> result = loadListGroupByDepartmentScItemResponse.getResult();
        if (CollectionUtils.isEmpty(result)) {
            return Lists.newArrayList();
        }
        List<Contract> groupList = Lists.newArrayList();
        int totalPage = getTotalPage(loadListGroupByDepartmentScItemResponse.getTotal(), LIMIT);
        for (int i = 1; i <= totalPage; i++) {
            LoadListGroupByDepartmentScItemRequest req = LoadListGroupByDepartmentScItemRequest.builder().contractYear(contractYear).start((i - 1) * LIMIT).limit(LIMIT).build();
            LoadListGroupByDepartmentScItemResponse res = contractService.loadListGroupByDepartmentScItem(req);
            List<Contract> contracts = res.getResult();
            if (CollectionUtils.isEmpty(contracts)) {
                continue;
            }
            groupList.addAll(contracts);
        }
        return groupList.stream().map(c -> {
            ContractSDO contractSDO = new ContractSDO();
            BeanUtils.copyProperties(c, contractSDO);
            contractSDO.setId(null);
            contractSDO.setDataSource(ContractDataSourceEnum.CUSTOMER.getCode());
            contractSDO.setType(ContractStatDimensionEnum.DEPARTMENT_SC_ITEM.getCode());
            return contractSDO;
        }).collect(Collectors.toList());
    }

    @Override
    @RepositoryInvoker
    public List<ContractSDO> queryGroupByEmployeeScItem(String contractYear) {

        LoadListGroupEmployeeScItemRequest request = LoadListGroupEmployeeScItemRequest.builder().start(0).limit(LIMIT).contractYear(contractYear).build();
        LoadListGroupEmployeeScItemResponse loadListGroupEmployeeScItemResponse = contractService.loadListGroupEmployeeScItem(request);
        List<Contract> result = loadListGroupEmployeeScItemResponse.getResult();
        if (CollectionUtils.isEmpty(result)) {
            return Lists.newArrayList();
        }
        List<Contract> groupList = Lists.newArrayList();
        int totalPage = getTotalPage(loadListGroupEmployeeScItemResponse.getTotal(), LIMIT);
        for (int i = 1; i <= totalPage; i++) {
            LoadListGroupEmployeeScItemRequest req = LoadListGroupEmployeeScItemRequest.builder().contractYear(contractYear).start((i - 1) * LIMIT).limit(LIMIT).build();
            LoadListGroupEmployeeScItemResponse res = contractService.loadListGroupEmployeeScItem(req);
            List<Contract> contracts = res.getResult();
            if (CollectionUtils.isEmpty(contracts)) {
                continue;
            }
            groupList.addAll(contracts);
        }
        return groupList.stream().map(c -> {
            ContractSDO contractSDO = new ContractSDO();
            BeanUtils.copyProperties(c, contractSDO);
            contractSDO.setId(null);
            contractSDO.setDataSource(ContractDataSourceEnum.CUSTOMER.getCode());
            contractSDO.setType(ContractStatDimensionEnum.EMPLOYEE_SC_ITEM.getCode());
            return contractSDO;
        }).collect(Collectors.toList());
    }

    @Override
    @RepositoryInvoker
    public List<ContractSDO> queryGroupBySalesChannelScItem(String contractYear) {

        LoadListGroupBySalesChannelScItemRequest request = LoadListGroupBySalesChannelScItemRequest.builder().start(0).limit(LIMIT).contractYear(contractYear).build();
        LoadListGroupBySalesChannelScItemResponse loadListGroupBySalesChannelScItemResponse = contractService.loadListGroupBySalesChannelScItem(request);
        List<Contract> result = loadListGroupBySalesChannelScItemResponse.getResult();
        if (CollectionUtils.isEmpty(result)) {
            return Lists.newArrayList();
        }
        List<Contract> groupList = Lists.newArrayList();
        int totalPage = getTotalPage(loadListGroupBySalesChannelScItemResponse.getTotal(), LIMIT);
        for (int i = 1; i <= totalPage; i++) {
            LoadListGroupBySalesChannelScItemRequest req = LoadListGroupBySalesChannelScItemRequest.builder().contractYear(contractYear).start((i - 1) * LIMIT).limit(LIMIT).build();
            LoadListGroupBySalesChannelScItemResponse res = contractService.loadListGroupBySalesChannelScItem(req);
            List<Contract> contracts = res.getResult();
            if (CollectionUtils.isEmpty(contracts)) {
                continue;
            }
            groupList.addAll(contracts);
        }
        return groupList.stream().map(c -> {
            ContractSDO contractSDO = new ContractSDO();
            BeanUtils.copyProperties(c, contractSDO);
            contractSDO.setId(null);
            contractSDO.setDataSource(ContractDataSourceEnum.CUSTOMER.getCode());
            contractSDO.setType(ContractStatDimensionEnum.SALES_CHANNEL_SC_ITEM.getCode());
            return contractSDO;
        }).collect(Collectors.toList());
    }

    @Override
    @RepositoryInvoker
    public List<ContractSDO> queryGroupBySalesOrgScItem(String contractYear) {

        LoadListGroupBySalesOrgScItemRequest request = LoadListGroupBySalesOrgScItemRequest.builder().start(0).limit(LIMIT).contractYear(contractYear).build();
        LoadListGroupBySalesOrgScItemResponse loadListGroupBySalesOrgScItemResponse = contractService.loadListGroupBySalesOrgScItem(request);
        List<Contract> result = loadListGroupBySalesOrgScItemResponse.getResult();
        if (CollectionUtils.isEmpty(result)) {
            return Lists.newArrayList();
        }
        List<Contract> groupList = Lists.newArrayList();
        int totalPage = getTotalPage(loadListGroupBySalesOrgScItemResponse.getTotal(), LIMIT);
        for (int i = 1; i <= totalPage; i++) {
            LoadListGroupBySalesOrgScItemRequest req = LoadListGroupBySalesOrgScItemRequest.builder().contractYear(contractYear).start((i - 1) * LIMIT).limit(LIMIT).build();
            LoadListGroupBySalesOrgScItemResponse res = contractService.loadListGroupBySalesOrgScItem(req);
            List<Contract> contracts = res.getResult();
            if (CollectionUtils.isEmpty(contracts)) {
                continue;
            }
            groupList.addAll(contracts);
        }
        return groupList.stream().map(c -> {
            ContractSDO contractSDO = new ContractSDO();
            BeanUtils.copyProperties(c, contractSDO);
            contractSDO.setId(null);
            contractSDO.setDataSource(ContractDataSourceEnum.CUSTOMER.getCode());
            contractSDO.setType(ContractStatDimensionEnum.SALES_ORG_SC_ITEM.getCode());
            return contractSDO;
        }).collect(Collectors.toList());
    }

    @Override
    @RepositoryInvoker
    public List<ContractSDO> queryGroupByCompany(String contractYear) {
        LoadListGroupByCompanyRequest request = LoadListGroupByCompanyRequest.builder().start(0).limit(LIMIT).contractYear(contractYear).build();
        LoadListGroupByCompanyResponse loadListGroupByCompanyResponse = contractService.loadListGroupByCompany(request);
        List<Contract> result = loadListGroupByCompanyResponse.getResult();
        if (CollectionUtils.isEmpty(result)) {
            return Lists.newArrayList();
        }
        List<Contract> groupList = Lists.newArrayList();
        int totalPage = getTotalPage(loadListGroupByCompanyResponse.getTotal(), LIMIT);
        for (int i = 1; i <= totalPage; i++) {
            LoadListGroupByCompanyRequest req = LoadListGroupByCompanyRequest.builder().contractYear(contractYear).start((i - 1) * LIMIT).limit(LIMIT).build();
            LoadListGroupByCompanyResponse res = contractService.loadListGroupByCompany(req);
            List<Contract> contracts = res.getResult();
            if (CollectionUtils.isEmpty(contracts)) {
                continue;
            }
            groupList.addAll(contracts);
        }
        return groupList.stream().map(c -> {
            ContractSDO contractSDO = new ContractSDO();
            BeanUtils.copyProperties(c, contractSDO);
            contractSDO.setId(null);
            contractSDO.setDataSource(ContractDataSourceEnum.CUSTOMER.getCode());
            contractSDO.setType(ContractStatDimensionEnum.COMPANY.getCode());
            return contractSDO;
        }).collect(Collectors.toList());
    }

    @Override
    @RepositoryInvoker
    public List<ContractSDO> queryGroupByCustomer(String contractYear) {
        LoadListGroupByCustomerRequest request = LoadListGroupByCustomerRequest.builder().start(0).limit(LIMIT).contractYear(contractYear).build();
        LoadListGroupByCustomerResponse loadListGroupByCustomerResponse = contractService.loadListGroupByCustomer(request);
        List<Contract> result = loadListGroupByCustomerResponse.getResult();
        if (CollectionUtils.isEmpty(result)) {
            return Lists.newArrayList();
        }
        List<Contract> groupList = Lists.newArrayList();
        int totalPage = getTotalPage(loadListGroupByCustomerResponse.getTotal(), LIMIT);
        for (int i = 1; i <= totalPage; i++) {
            LoadListGroupByCustomerRequest req = LoadListGroupByCustomerRequest.builder().contractYear(contractYear).start((i - 1) * LIMIT).limit(LIMIT).build();
            LoadListGroupByCustomerResponse res = contractService.loadListGroupByCustomer(req);
            if (res == null || CollectionUtils.isEmpty(res.getResult())) {
                continue;
            }
            List<Contract> contracts = res.getResult();
            groupList.addAll(contracts);
        }
        return groupList.stream().map(c -> {
            ContractSDO contractSDO = new ContractSDO();
            BeanUtils.copyProperties(c, contractSDO);
            contractSDO.setId(null);
            contractSDO.setDataSource(ContractDataSourceEnum.CUSTOMER.getCode());
            contractSDO.setType(ContractStatDimensionEnum.CUSTOMER.getCode());
            return contractSDO;
        }).collect(Collectors.toList());
    }

    @Override
    @RepositoryInvoker
    public List<ContractSDO> queryGroupByDepartment(String contractYear) {
        LoadListGroupByDepartmentRequest request = LoadListGroupByDepartmentRequest.builder().start(0).limit(LIMIT).contractYear(contractYear).build();
        LoadListGroupByDepartmentResponse loadListGroupByDepartmentResponse = contractService.loadListGroupByDepartment(request);
        List<Contract> result = loadListGroupByDepartmentResponse.getResult();
        if (CollectionUtils.isEmpty(result)) {
            return Lists.newArrayList();
        }
        List<Contract> groupList = Lists.newArrayList();
        int totalPage = getTotalPage(loadListGroupByDepartmentResponse.getTotal(), LIMIT);
        for (int i = 1; i <= totalPage; i++) {
            LoadListGroupByDepartmentRequest req = LoadListGroupByDepartmentRequest.builder().contractYear(contractYear).start((i - 1) * LIMIT).limit(LIMIT).build();
            LoadListGroupByDepartmentResponse res = contractService.loadListGroupByDepartment(req);
            List<Contract> contracts = res.getResult();
            if (CollectionUtils.isEmpty(contracts)) {
                continue;
            }
            groupList.addAll(contracts);
        }
        return groupList.stream().map(c -> {
            ContractSDO contractSDO = new ContractSDO();
            BeanUtils.copyProperties(c, contractSDO);
            contractSDO.setId(null);
            contractSDO.setDataSource(ContractDataSourceEnum.CUSTOMER.getCode());
            contractSDO.setType(ContractStatDimensionEnum.DEPARTMENT.getCode());
            return contractSDO;
        }).collect(Collectors.toList());
    }

    @Override
    @RepositoryInvoker
    public List<ContractSDO> queryGroupByEmployee(String contractYear) {

        LoadListGroupEmployeeRequest request = LoadListGroupEmployeeRequest.builder().start(0).limit(LIMIT).contractYear(contractYear).build();
        LoadListGroupEmployeeResponse loadListGroupEmployeeResponse = contractService.loadListGroupEmployee(request);
        List<Contract> result = loadListGroupEmployeeResponse.getResult();
        if (CollectionUtils.isEmpty(result)) {
            return Lists.newArrayList();
        }
        List<Contract> groupList = Lists.newArrayList();
        int totalPage = getTotalPage(loadListGroupEmployeeResponse.getTotal(), LIMIT);
        for (int i = 1; i <= totalPage; i++) {
            LoadListGroupEmployeeRequest req = LoadListGroupEmployeeRequest.builder().contractYear(contractYear).start((i - 1) * LIMIT).limit(LIMIT).build();
            LoadListGroupEmployeeResponse res = contractService.loadListGroupEmployee(req);
            List<Contract> contracts = res.getResult();
            if (CollectionUtils.isEmpty(contracts)) {
                continue;
            }
            groupList.addAll(contracts);
        }
        return groupList.stream().map(c -> {
            ContractSDO contractSDO = new ContractSDO();
            BeanUtils.copyProperties(c, contractSDO);
            contractSDO.setId(null);
            contractSDO.setDataSource(ContractDataSourceEnum.CUSTOMER.getCode());
            contractSDO.setType(ContractStatDimensionEnum.EMPLOYEE.getCode());
            return contractSDO;
        }).collect(Collectors.toList());
    }

    @Override
    @RepositoryInvoker
    public List<ContractSDO> queryGroupBySalesChannel(String contractYear) {

        LoadListGroupBySalesChannelRequest request = LoadListGroupBySalesChannelRequest.builder().start(0).limit(LIMIT).contractYear(contractYear).build();
        LoadListGroupBySalesChannelResponse loadListGroupBySalesChannelResponse = contractService.loadListGroupBySalesChannel(request);
        List<Contract> result = loadListGroupBySalesChannelResponse.getResult();
        if (CollectionUtils.isEmpty(result)) {
            return Lists.newArrayList();
        }
        List<Contract> groupList = Lists.newArrayList();
        int totalPage = getTotalPage(loadListGroupBySalesChannelResponse.getTotal(), LIMIT);
        for (int i = 1; i <= totalPage; i++) {
            LoadListGroupBySalesChannelRequest req = LoadListGroupBySalesChannelRequest.builder().contractYear(contractYear).start((i - 1) * LIMIT).limit(LIMIT).build();
            LoadListGroupBySalesChannelResponse res = contractService.loadListGroupBySalesChannel(req);
            List<Contract> contracts = res.getResult();
            if (CollectionUtils.isEmpty(contracts)) {
                continue;
            }
            groupList.addAll(contracts);
        }
        return groupList.stream().map(c -> {
            ContractSDO contractSDO = new ContractSDO();
            BeanUtils.copyProperties(c, contractSDO);
            contractSDO.setId(null);
            contractSDO.setDataSource(ContractDataSourceEnum.CUSTOMER.getCode());
            contractSDO.setType(ContractStatDimensionEnum.SALES_CHANNEL.getCode());
            return contractSDO;
        }).collect(Collectors.toList());
    }

    @Override
    @RepositoryInvoker
    public List<ContractSDO> queryGroupByCompanyCategory(String contractYear) {
        LoadListGroupByCompanyCategoryRequest request = LoadListGroupByCompanyCategoryRequest.builder().start(0).limit(LIMIT).contractYear(contractYear).build();
        LoadListGroupByCompanyCategoryResponse loadListGroupByCompanyCategoryResponse = contractService.loadListGroupByCompanyCategory(request);
        List<Contract> result = loadListGroupByCompanyCategoryResponse.getResult();
        if (CollectionUtils.isEmpty(result)) {
            return Lists.newArrayList();
        }
        List<Contract> groupList = Lists.newArrayList();
        int totalPage = getTotalPage(loadListGroupByCompanyCategoryResponse.getTotal(), LIMIT);
        for (int i = 1; i <= totalPage; i++) {
            LoadListGroupByCompanyCategoryRequest req = LoadListGroupByCompanyCategoryRequest.builder().contractYear(contractYear).start((i - 1) * LIMIT).limit(LIMIT).build();
            LoadListGroupByCompanyCategoryResponse res = contractService.loadListGroupByCompanyCategory(req);
            List<Contract> contracts = res.getResult();
            if (CollectionUtils.isEmpty(contracts)) {
                continue;
            }
            groupList.addAll(contracts);
        }
        return groupList.stream().map(c -> {
            ContractSDO contractSDO = new ContractSDO();
            BeanUtils.copyProperties(c, contractSDO);
            contractSDO.setId(null);
            contractSDO.setDataSource(ContractDataSourceEnum.CUSTOMER.getCode());
            contractSDO.setType(ContractStatDimensionEnum.COMPANY_CATEGORY.getCode());
            return contractSDO;
        }).collect(Collectors.toList());
    }

    @Override
    @RepositoryInvoker
    public List<ContractSDO> queryGroupByDepartmentCategory(String contractYear) {
        LoadListGroupByDepartmentSCategoryRequest request = LoadListGroupByDepartmentSCategoryRequest.builder().start(0).limit(LIMIT).contractYear(contractYear).build();
        LoadListGroupByDepartmentSCategoryResponse loadListGroupByDepartmentSCategoryResponse = contractService.loadListGroupByDepartmentSCategory(request);
        List<Contract> result = loadListGroupByDepartmentSCategoryResponse.getResult();
        if (CollectionUtils.isEmpty(result)) {
            return Lists.newArrayList();
        }

        List<Contract> groupList = Lists.newArrayList();
        int totalPage = getTotalPage(loadListGroupByDepartmentSCategoryResponse.getTotal(), LIMIT);
        for (int i = 1; i <= totalPage; i++) {
            LoadListGroupByDepartmentSCategoryRequest req = LoadListGroupByDepartmentSCategoryRequest.builder().contractYear(contractYear).start((i - 1) * LIMIT).limit(LIMIT).build();
            LoadListGroupByDepartmentSCategoryResponse res = contractService.loadListGroupByDepartmentSCategory(req);
            List<Contract> contracts = res.getResult();
            if (CollectionUtils.isEmpty(contracts)) {
                continue;
            }
            groupList.addAll(contracts);
        }
        return groupList.stream().map(c -> {
            ContractSDO contractSDO = new ContractSDO();
            BeanUtils.copyProperties(c, contractSDO);
            contractSDO.setId(null);
            contractSDO.setDataSource(ContractDataSourceEnum.CUSTOMER.getCode());
            contractSDO.setType(ContractStatDimensionEnum.DEPARTMENT_CATEGORY.getCode());
            return contractSDO;
        }).collect(Collectors.toList());
    }

    private int getTotalPage(Integer total, int limit) {
        if (total % limit == 0) {
            return total / limit;
        } else {
            return (total / limit) + 1;
        }
    }

    @Override
    @RepositoryInvoker
    public List<ContractSDO> queryGroupByEmployeeCategory(String contractYear) {
        LoadListGroupEmployeeCategoryRequest request = LoadListGroupEmployeeCategoryRequest.builder().start(0).limit(LIMIT).contractYear(contractYear).build();
        LoadListGroupEmployeeCategoryResponse loadListGroupEmployeeCategoryResponse = contractService.loadListGroupEmployeeCategory(request);
        List<Contract> result = loadListGroupEmployeeCategoryResponse.getResult();
        if (CollectionUtils.isEmpty(result)) {
            return Lists.newArrayList();
        }
        List<Contract> groupList = Lists.newArrayList();
        int totalPage = getTotalPage(loadListGroupEmployeeCategoryResponse.getTotal(), LIMIT);
        for (int i = 1; i <= totalPage; i++) {
            LoadListGroupEmployeeCategoryRequest req = LoadListGroupEmployeeCategoryRequest.builder().contractYear(contractYear).start((i - 1) * LIMIT).limit(LIMIT).build();
            LoadListGroupEmployeeCategoryResponse res = contractService.loadListGroupEmployeeCategory(req);
            List<Contract> contracts = res.getResult();
            if (CollectionUtils.isEmpty(contracts)) {
                continue;
            }
            groupList.addAll(contracts);
        }
        return groupList.stream().map(c -> {
            ContractSDO contractSDO = new ContractSDO();
            BeanUtils.copyProperties(c, contractSDO);
            contractSDO.setId(null);
            contractSDO.setDataSource(ContractDataSourceEnum.CUSTOMER.getCode());
            contractSDO.setType(ContractStatDimensionEnum.EMPLOYEE_CATEGORY.getCode());
            return contractSDO;
        }).collect(Collectors.toList());
    }

    @Override
    @RepositoryInvoker
    public List<String> queryContractYear() {
        QueryContractYearResponse queryContractYearResponse = contractService.queryContractYear();
        if (queryContractYearResponse != null) {
            return queryContractYearResponse.getResult();
        }
        return null;
    }

    @Override
    @RepositoryInvoker
    public Boolean deleteStatContract(List<String> contractYearList) {
        DeleteStatContractRequest request = new DeleteStatContractRequest();
        request.setContractYearList(contractYearList);
        contractService.deleteStatContract(request);
        return true;
    }

    @Override
    @RepositoryInvoker
    public PageResult<List<ContractSDO>> pageQueryDepartByRedCount(PageQueryContractRequest contractRequest) {
        if (StringUtils.isNotBlank(contractRequest.getOutrId())) {
            //根据外部编码获得scItemId
            SearchScItemRequest searchScItemRequest = new SearchScItemRequest();
            Map searchReqDTO = new HashMap();
            searchReqDTO.put("outerId", contractRequest.getOutrId());
            searchScItemRequest.setSearchReqDTO(searchReqDTO);
            Result<List<ScItemSDO>> listResult = baseDataService.searchScItem(searchScItemRequest);
            if (listResult.getResult().isEmpty()){
                throw new RepositoryException("OTS-02-001-00-15-0011");
            }
            List<String> scItemIdList = listResult.getResult().stream().map(ScItemSDO::getScItemId).filter(StringUtils::isNotBlank).collect(Collectors.toList());
            if (CollectionUtils.isNotEmpty(scItemIdList)) {
                contractRequest.setScItemIds(scItemIdList);
                if (StringUtils.isNotBlank(contractRequest.getScItemId())) {
                    if (scItemIdList.contains(contractRequest.getScItemId())) {
                        contractRequest.setScItemIds(Lists.newArrayList(contractRequest.getScItemId()));
                    } else {
                        throw new RepositoryException("OTS-02-001-00-15-0010");
                    }
                }
            } else {
                throw new RepositoryException("OTS-02-001-00-15-0011");
            }
//            if (StringUtils.isNotBlank(contractRequest.getScItemId())){
//                if (scItemSDO.getScItemId().equals(contractRequest.getScItemId())){
//                    contractRequest.setScItemId(scItemSDO.getScItemId());
//                }else {
//                    throw new RepositoryException("OTS-02-OO1-OO-15-0010");
//                }
//            }else {
//                contractRequest.setScItemId(scItemSDO.getScItemId());
//            }

        }
        if (StringUtils.isNotBlank(contractRequest.getScItemId())) {
            if (CollectionUtils.isEmpty(contractRequest.getScItemIds())) {
                contractRequest.setScItemIds(Lists.newArrayList(contractRequest.getScItemId()));
            }
        }
        PageQueryContractListRequest pageQueryContractListRequest = contractQueryRequestConverter(contractRequest);
        PageQueryContractListResponse pageQueryContractListResponse = contractService.pageQueryContractList(pageQueryContractListRequest);
        List<Contract> result = pageQueryContractListResponse.getResult();
        if (CollectionUtils.isEmpty(result)) {
            return new PageResult<>();
        }
        List<String> contractYears = result.stream().map(Contract::getContractYear).distinct().collect(Collectors.toList());
        List<String> departs = result.stream().map(Contract::getOrgSalesDepartmentCode).distinct().collect(Collectors.toList());
        List<String> scItemIds = result.stream().map(Contract::getScItemId).distinct().collect(Collectors.toList());
        BaselineGetOrganizationByIds2Request build = BaselineGetOrganizationByIds2Request.builder().ids(departs).status(1).build();
        BaselineGetOrganizationByIds2Response byIds2Response = baseDataService.baselineGetOrganizationByIds2(build);
        Map<String, ScItemSDO> scItemSDOMap = Maps.newHashMap();
        if (CollectionUtils.isNotEmpty(scItemIds)) {
            SearchScItemRequest searchScItemRequest = new SearchScItemRequest();
            JSONObject searchReqDTO = new JSONObject();
            searchReqDTO.put("scItemIds", scItemIds);
            searchReqDTO.put("statusList", Lists.newArrayList(1,-1));
            searchScItemRequest.setPageSize(scItemIds.size());
            searchScItemRequest.setSearchReqDTO(searchReqDTO);
            Result<List<com.epoch.app.bcots.model.dto.ScItemSDO>> scItem = baseDataService.searchScItem(searchScItemRequest);
            if (scItem != null && CollectionUtils.isNotEmpty(scItem.getResult())) {
                scItemSDOMap = scItem.getResult().stream().collect(Collectors.toMap(com.epoch.app.bcots.model.dto.ScItemSDO::getScItemId, s -> s));
            }
        }
        Map<String, OrganizationSDO> organizationSDOMap = Maps.newHashMap();
        if (byIds2Response != null && CollectionUtils.isNotEmpty(byIds2Response.getResult())) {
            organizationSDOMap = byIds2Response.getResult().stream().collect(Collectors.toMap(OrganizationSDO::getId, o -> o));
        }
        // 转换
        Map<String, OrganizationSDO> finalOrganizationSDOMap = organizationSDOMap;
        Map<String, ScItemSDO> finalScItemSDOMap = scItemSDOMap;
        List<ContractSDO> contractSDOS = result.stream().map(it -> {
            ContractSDO contractSDO = new ContractSDO();
            BeanUtils.copyProperties(it, contractSDO);
            // id转名称赋值
            OrganizationSDO organizationSDO = finalOrganizationSDOMap.get(contractSDO.getOrgSalesDepartmentCode());
            if (null != organizationSDO) {
                contractSDO.setOrgSalesDepartmentName(organizationSDO.getName());
            }
            ScItemSDO scItemSDO = finalScItemSDOMap.get(contractSDO.getScItemId());
            if (null != scItemSDO) {
                contractSDO.setScItemName(scItemSDO.getTitle());
                contractSDO.setScItemCode(scItemSDO.getOuterId());
            }
            return contractSDO;
        }).collect(Collectors.toList());

        BatchQueryDepartmentContractRequest departmentContractRequest = BatchQueryDepartmentContractRequest.builder().contractYears(contractYears).scItemIds(scItemIds).orgSalesDepartmentCodes(departs).build();
        BatchQueryDepartmentContractResponse batchQueryDepartmentContractResponse = departmentContractRedLineService.batchQueryDepartmentContract(departmentContractRequest);
        List<DepartmentContractRedLine> redLines = batchQueryDepartmentContractResponse.getResult();
        if (CollectionUtils.isEmpty(redLines)) {
            List<ContractSDO> contractSDOList = contractSDOS.stream().map(it -> {
                setAmountString(it);
                return it;
            }).collect(Collectors.toList());
            return PageResult.of(contractSDOList, pageQueryContractListResponse.getTotal());
        }

        List<ContractSDO> contractList = contractSDOS.stream().map(sdo -> {
            List<DepartmentContractRedLine> collect = redLines.stream().filter(it ->
                    it.getContractYear().equals(sdo.getContractYear())
                            && it.getOrgSalesDepartmentCode().equals(sdo.getOrgSalesDepartmentCode())
                            && it.getScItemId().equals(sdo.getScItemId())).collect(Collectors.toList());

            if (collect.size() == 1) {
                DepartmentContractRedLine depart = collect.stream().findFirst().get();
                setDepartRedCount(sdo, depart);
            }
            setAmountString(sdo);
            return sdo;
        }).collect(Collectors.toList());

        return PageResult.of(contractList, pageQueryContractListResponse.getTotal());
    }

    private void setDepartRedCount(ContractSDO contractSDO, DepartmentContractRedLine depart) {
        contractSDO.setJanRedCount(depart.getJanRedCount());
        contractSDO.setFebRedCount(depart.getFebRedCount());
        contractSDO.setMarRedCount(depart.getMarRedCount());
        contractSDO.setAprRedCount(depart.getAprRedCount());
        contractSDO.setMayRedCount(depart.getMayRedCount());
        contractSDO.setJuneRedCount(depart.getJuneRedCount());
        contractSDO.setJulyRedCount(depart.getJulyRedCount());
        contractSDO.setAugRedCount(depart.getAugRedCount());
        contractSDO.setSeptRedCount(depart.getSeptRedCount());
        contractSDO.setOctRedCount(depart.getOctRedCount());
        contractSDO.setNovRedCount(depart.getNovRedCount());
        contractSDO.setDecRedCount(depart.getDecRedCount());

        contractSDO.setJanRedRatio(depart.getJanRedRatio());
        contractSDO.setFebRedRatio(depart.getFebRedRatio());
        contractSDO.setMarRedRatio(depart.getMarRedRatio());
        contractSDO.setAprRedRatio(depart.getAprRedRatio());
        contractSDO.setMayRedRatio(depart.getMayRedRatio());
        contractSDO.setJuneRedRatio(depart.getJuneRedRatio());
        contractSDO.setJulyRedRatio(depart.getJulyRedRatio());
        contractSDO.setAugRedRatio(depart.getAugRedRatio());
        contractSDO.setSeptRedRatio(depart.getSeptRedRatio());
        contractSDO.setOctRedRatio(depart.getOctRedRatio());
        contractSDO.setNovRedRatio(depart.getNovRedRatio());
        contractSDO.setDecRedRatio(depart.getDecRedRatio());
    }

    @Override
    public PageResult<List<ContractSDO>> searchContract(SearchContractRepoReq searchContractRepoReq) {
        BatchQueryRequest queryRequest = new BatchQueryRequest();
        queryRequest.setTypeList(searchContractRepoReq.getTypeList());
        queryRequest.setContractYearList(searchContractRepoReq.getContractYearList());
        queryRequest.setCustomerCodeList(searchContractRepoReq.getCustomerCodeList());
        queryRequest.setCustomerAddressList(searchContractRepoReq.getCustomerAddressList());
        queryRequest.setScItemIdList(searchContractRepoReq.getScItemIdList());
        queryRequest.setOrgBusinessUnitCodeList(searchContractRepoReq.getOrgBusinessUnitCodeList());
        queryRequest.setOrgSalesOrganizationCodeList(searchContractRepoReq.getOrgSalesOrganizationCodeList());
        queryRequest.setOrgSalesChannelCodeList(searchContractRepoReq.getOrgSalesChannelCodeList());
        queryRequest.setOrgSalesDepartmentCodeList(searchContractRepoReq.getOrgSalesDepartmentCodeList());
        queryRequest.setChannelCodeList(searchContractRepoReq.getChannelCodeList());
        queryRequest.setManageEmployeeIdList(searchContractRepoReq.getManageEmployeeIdList());
        queryRequest.setScItemCategoryIdList(searchContractRepoReq.getScItemCategoryIdList());
        queryRequest.setStart(searchContractRepoReq.getStart());
        queryRequest.setLimit(searchContractRepoReq.getLimit());
        queryRequest.setCustomerAddressIdList(searchContractRepoReq.getCustomerAddressIdList());
        queryRequest.setDataSourceList(searchContractRepoReq.getDataSourceList());
        BatchQueryResponse batchQueryResponse = boSalesPlanContractInfoIndexService.batchQuery(queryRequest);
        if (batchQueryResponse == null || CollectionUtils.isEmpty(batchQueryResponse.getResult())){
            return new PageResult<>();
        }
        List<ContractSDO> result = batchQueryResponse.getResult().stream().map(contract -> {
            ContractSDO sdo = new ContractSDO();
            BeanUtils.copyProperties(contract,sdo);
            return sdo;
        }).collect(Collectors.toList());


        return new PageResult<>(result,batchQueryResponse.getTotal());
    }

    @Override
    public Integer queryCountByYear(QueryCountByYearRequest request) {
        com.epoch.app.bcots.sales_plan.contract.dto.QueryCountByYearRequest byYearRequest = new com.epoch.app.bcots.sales_plan.contract.dto.QueryCountByYearRequest();
        byYearRequest.setYear(request.getYear());
        byYearRequest.setType(request.getType());
        QueryCountByYearResponse queryCountByYearResponse = contractService.queryCountByYear(byYearRequest);
        if (queryCountByYearResponse == null || queryCountByYearResponse.getTotal() == null){
            return 0;
        }
        return queryCountByYearResponse.getTotal();
    }

    @Override
    public PageResult<List<ContractSDO>> pageQueryContract(SearchContractRepoReq searchContractRepoReq) {
        PageQueryContractListRequest request = new PageQueryContractListRequest();
        request.setTypeList(searchContractRepoReq.getTypeList());
        request.setContractYearList(searchContractRepoReq.getContractYearList());
        request.setCustomerCodes(searchContractRepoReq.getCustomerCodeList());
        request.setCustomerAddresses(searchContractRepoReq.getCustomerAddressList());
        request.setScItemIds(searchContractRepoReq.getScItemIdList());
        request.setOrgBusinessUnitCodeList(searchContractRepoReq.getOrgBusinessUnitCodeList());
        request.setOrgSalesOrganizationCodeList(searchContractRepoReq.getOrgSalesOrganizationCodeList());
        request.setOrgSalesChannelCodeList(searchContractRepoReq.getOrgSalesChannelCodeList());
        request.setOrgSalesDepartmentCodeList(searchContractRepoReq.getOrgSalesDepartmentCodeList());
        request.setChannelCodeList(searchContractRepoReq.getChannelCodeList());
        request.setManageEmployeeIdList(searchContractRepoReq.getManageEmployeeIdList());
        request.setScItemCategoryIdList(searchContractRepoReq.getScItemCategoryIdList());
        request.setCustomerAddressIdList(searchContractRepoReq.getCustomerAddressIdList());
        request.setDataSourceList(searchContractRepoReq.getDataSourceList());
        request.setSize(SIZE);
        log.info("ContractFileService.customerImportHandle.pageQueryContractList.request={}", JSONObject.toJSONString(request));
        int start = ZERO;
        Integer total = ZERO;
        List<Contract> contractList = Lists.newArrayList();
        while (start <= total) {
            request.setStart(start);
            PageQueryContractListResponse listResponse = contractService.pageQueryContractList(request);
            if (CollectionUtils.isNotEmpty(listResponse.getResult())) {
                contractList.addAll(listResponse.getResult());
            }
            total = listResponse.getTotal();
            start += SIZE;
        }
        if (contractList.size() == ZERO) {
            return new PageResult<>(Lists.newArrayList(), ZERO);
        }
        List<ContractSDO> result = contractList.stream().map(contract -> {
            ContractSDO sdo = new ContractSDO();
            BeanUtils.copyProperties(contract,sdo);
            return sdo;
        }).collect(Collectors.toList());
        return new PageResult<>(result, total);
    }

    @Override
    @RepositoryInvoker
    public List<ContractSDO> queryGroupBySalesChannelCategory(String contractYear) {
        LoadListGroupBySalesChannelCategoryRequest request = LoadListGroupBySalesChannelCategoryRequest.builder().start(0).limit(LIMIT).contractYear(contractYear).build();
        LoadListGroupBySalesChannelCategoryResponse loadListGroupBySalesChannelCategoryResponse = contractService.loadListGroupBySalesChannelCategory(request);
        List<Contract> result = loadListGroupBySalesChannelCategoryResponse.getResult();
        if (CollectionUtils.isEmpty(result)) {
            return Lists.newArrayList();
        }
        List<Contract> groupList = Lists.newArrayList();
        int totalPage = getTotalPage(loadListGroupBySalesChannelCategoryResponse.getTotal(), LIMIT);
        for (int i = 1; i <= totalPage; i++) {
            LoadListGroupBySalesChannelCategoryRequest req = LoadListGroupBySalesChannelCategoryRequest.builder().contractYear(contractYear).start((i - 1) * LIMIT).limit(LIMIT).build();
            LoadListGroupBySalesChannelCategoryResponse res = contractService.loadListGroupBySalesChannelCategory(req);
            List<Contract> contracts = res.getResult();
            if (CollectionUtils.isEmpty(contracts)) {
                continue;
            }
            groupList.addAll(contracts);
        }
        return groupList.stream().map(c -> {
            ContractSDO contractSDO = new ContractSDO();
            BeanUtils.copyProperties(c, contractSDO);
            contractSDO.setId(null);
            contractSDO.setDataSource(ContractDataSourceEnum.CUSTOMER.getCode());
            contractSDO.setType(ContractStatDimensionEnum.SALES_CHANNEL_CATEGORY.getCode());
            return contractSDO;
        }).collect(Collectors.toList());
    }

    @Override
    @RepositoryInvoker
    public List<ContractSDO> queryGroupBySalesOrganization(String contractYear) {

        LoadListGroupBySalesOrgRequest request = LoadListGroupBySalesOrgRequest.builder().start(0).limit(LIMIT).contractYear(contractYear).build();
        LoadListGroupBySalesOrgResponse loadListGroupBySalesOrgResponse = contractService.loadListGroupBySalesOrg(request);
        List<Contract> result = loadListGroupBySalesOrgResponse.getResult();
        if (CollectionUtils.isEmpty(result)) {
            return Lists.newArrayList();
        }
        List<Contract> groupList = Lists.newArrayList();
        int totalPage = getTotalPage(loadListGroupBySalesOrgResponse.getTotal(), LIMIT);
        for (int i = 1; i <= totalPage; i++) {
            LoadListGroupBySalesOrgRequest req = LoadListGroupBySalesOrgRequest.builder().contractYear(contractYear).start((i - 1) * LIMIT).limit(LIMIT).build();
            LoadListGroupBySalesOrgResponse res = contractService.loadListGroupBySalesOrg(req);
            List<Contract> contracts = res.getResult();
            if (CollectionUtils.isEmpty(contracts)) {
                continue;
            }
            groupList.addAll(contracts);
        }
        return groupList.stream().map(c -> {
            ContractSDO contractSDO = new ContractSDO();
            BeanUtils.copyProperties(c, contractSDO);
            contractSDO.setId(null);
            contractSDO.setDataSource(ContractDataSourceEnum.CUSTOMER.getCode());
            contractSDO.setType(ContractStatDimensionEnum.SALES_ORGANIZATION.getCode());
            return contractSDO;
        }).collect(Collectors.toList());
    }

    @Override
    @RepositoryInvoker
    public List<ContractSDO> queryGroupBySalesOrgCategory(String contractYear) {
        LoadListGroupBySalesOrgCategoryRequest request = LoadListGroupBySalesOrgCategoryRequest.builder().start(0).limit(LIMIT).contractYear(contractYear).build();
        LoadListGroupBySalesOrgCategoryResponse loadListGroupBySalesOrgCategoryResponse = contractService.loadListGroupBySalesOrgCategory(request);
        List<Contract> result = loadListGroupBySalesOrgCategoryResponse.getResult();
        if (CollectionUtils.isEmpty(result)) {
            return Lists.newArrayList();
        }
        List<Contract> groupList = Lists.newArrayList();
        int totalPage = getTotalPage(loadListGroupBySalesOrgCategoryResponse.getTotal(), LIMIT);
        for (int i = 1; i <= totalPage; i++) {
            LoadListGroupBySalesOrgCategoryRequest req = LoadListGroupBySalesOrgCategoryRequest.builder().contractYear(contractYear).start((i - 1) * LIMIT).limit(LIMIT).build();
            LoadListGroupBySalesOrgCategoryResponse res = contractService.loadListGroupBySalesOrgCategory(req);
            List<Contract> contracts = res.getResult();
            if (CollectionUtils.isEmpty(contracts)) {
                continue;
            }
            groupList.addAll(contracts);
        }
        return groupList.stream().map(c -> {
            ContractSDO contractSDO = new ContractSDO();
            BeanUtils.copyProperties(c, contractSDO);
            contractSDO.setId(null);
            contractSDO.setDataSource(ContractDataSourceEnum.CUSTOMER.getCode());
            contractSDO.setType(ContractStatDimensionEnum.SALES_ORG_CATEGORY.getCode());
            return contractSDO;
        }).collect(Collectors.toList());
    }


    private Contract contractCreateConverter(ContractSDO contractSDO) {
        Contract contract = new Contract();
        BeanUtils.copyProperties(contractSDO, contract);
        return contract;
    }

    private Contract contractUpdateRequestConverter(ContractSDO editContractRequest) {
        Contract contract = new Contract();
        BeanUtils.copyProperties(editContractRequest, contract);
        return contract;
    }

    private LoadContractRequest contractRequestConverter(QueryContractRequest queryContractRequest) {
        LoadContractRequest loadRequest = LoadContractRequest.builder().build();
        BeanUtils.copyProperties(queryContractRequest, loadRequest);
        return loadRequest;
    }

    private PageQueryContractListRequest contractQueryRequestConverter(PageQueryContractRequest pageQueryContractRequest) {
        PageQueryContractListRequest loadListRequest = new PageQueryContractListRequest();
        if (CollectionUtils.isEmpty(pageQueryContractRequest.getScItemIds())) {
            pageQueryContractRequest.setScItemIds(null);
        }
        if (CollectionUtils.isEmpty(pageQueryContractRequest.getCustomerCodes())) {
            pageQueryContractRequest.setCustomerCodes(null);
        }
        if (CollectionUtils.isEmpty(pageQueryContractRequest.getCustomerAddresses())) {
            pageQueryContractRequest.setCustomerAddresses(null);
        }
        BeanUtils.copyProperties(pageQueryContractRequest, loadListRequest);
        return loadListRequest;
    }

    private Contract contractCreateRequestConverter(CreateContractRequest createContractRequest) {
        Contract createRequest = new Contract();
        BeanUtils.copyProperties(createContractRequest, createRequest);
        return createRequest;
    }

    private void fillContractCountAndAmount(Map<String, Integer> contractCountToMap, Map<String, Long> amountToMap, Map<String, Long> contractBeforeAmountToMap, MonthContractAndRollingCountResponse response, QueryContractByCustomerDimensionRequest dimensionRequest) {
        //设置合同量和m1、m2、m3合同量
        AtomicInteger month = new AtomicInteger(Integer.parseInt(dimensionRequest.getPlanMonth()));
        response.setMonthContractCount(contractCountToMap.get(month.get() + ""));
        response.setM1RollingPlanCount(contractCountToMap.get(month.incrementAndGet() + ""));
        response.setM2RollingPlanCount(contractCountToMap.get(month.incrementAndGet() + ""));
        response.setM3RollingPlanCount(contractCountToMap.get(month.incrementAndGet() + ""));
        // 设置合同金额和m1、m2、m3合同金额
        response.setM3RollingPlanMoney(amountToMap.get(month.get() + ""));
        response.setM2RollingPlanMoney(amountToMap.get(month.decrementAndGet() + ""));
        response.setM1RollingPlanMoney(amountToMap.get(month.decrementAndGet() + ""));
        response.setMonthContractMoney(amountToMap.get(month.decrementAndGet() + ""));

        // 设置折前金额和m1、m2、m3折前金额
        response.setBeforeMonthContractMoney(contractBeforeAmountToMap.get(month.get() + ""));
        response.setM1BeforeMonthContractMoney(contractBeforeAmountToMap.get(month.incrementAndGet() + ""));
        response.setM2BeforeMonthContractMoney(contractBeforeAmountToMap.get(month.incrementAndGet() + ""));
        response.setM3BeforeMonthContractMoney(contractBeforeAmountToMap.get(month.incrementAndGet() + ""));
    }

    private Map<String, Long> converterContractAmountToMap(Contract it) {
        HashMap<String, Long> contractCountMap = new HashMap<>();
        contractCountMap.put("1", it.getJanAmount());
        contractCountMap.put("2", it.getFebAmount());
        contractCountMap.put("3", it.getMarAmount());
        contractCountMap.put("4", it.getAprAmount());
        contractCountMap.put("5", it.getMayAmount());
        contractCountMap.put("6", it.getJuneAmount());
        contractCountMap.put("7", it.getJulyAmount());
        contractCountMap.put("8", it.getAugAmount());
        contractCountMap.put("9", it.getSeptAmount());
        contractCountMap.put("10", it.getOctAmount());
        contractCountMap.put("11", it.getNovAmount());
        contractCountMap.put("12", it.getDecAmount());
        return contractCountMap;
    }

    private Map<String, Integer> converterContractCountToMap(Contract it) {
        HashMap<String, Integer> contractCountMap = new HashMap<>();
        contractCountMap.put("1", it.getJanQuantity());
        contractCountMap.put("2", it.getFebQuantity());
        contractCountMap.put("3", it.getMarQuantity());
        contractCountMap.put("4", it.getAprQuantity());
        contractCountMap.put("5", it.getMayQuantity());
        contractCountMap.put("6", it.getJuneQuantity());
        contractCountMap.put("7", it.getJulyQuantity());
        contractCountMap.put("8", it.getAugQuantity());
        contractCountMap.put("9", it.getSeptQuantity());
        contractCountMap.put("10", it.getOctQuantity());
        contractCountMap.put("11", it.getNovQuantity());
        contractCountMap.put("12", it.getDecQuantity());
        return contractCountMap;
    }

    private Map<String, Long> converterContractBeforeAmountToMap(Contract it) {
        HashMap<String, Long> contractBeforeAmountToMap = new HashMap<>();
        contractBeforeAmountToMap.put("1", it.getJanTaxIncludedBeforeTax());
        contractBeforeAmountToMap.put("2", it.getFebTaxIncludedBeforeTax());
        contractBeforeAmountToMap.put("3", it.getMarTaxIncludedBeforeTax());
        contractBeforeAmountToMap.put("4", it.getAprTaxIncludedBeforeTax());
        contractBeforeAmountToMap.put("5", it.getMayTaxIncludedBeforeTax());
        contractBeforeAmountToMap.put("6", it.getJuneTaxIncludedBeforeTax());
        contractBeforeAmountToMap.put("7", it.getJulyTaxIncludedBeforeTax());
        contractBeforeAmountToMap.put("8", it.getAugTaxIncludedBeforeTax());
        contractBeforeAmountToMap.put("9", it.getSeptTaxIncludedBeforeTax());
        contractBeforeAmountToMap.put("10", it.getOctTaxIncludedBeforeTax());
        contractBeforeAmountToMap.put("11", it.getNovTaxIncludedBeforeTax());
        contractBeforeAmountToMap.put("12", it.getDecTaxIncludedBeforeTax());
        return contractBeforeAmountToMap;
    }

    private String getDoubleString(Long value) {
        if (Objects.isNull(value)) {
            return "0.00";
        }
        DecimalFormat df = new DecimalFormat("######0.00");
        double doubleValue = value / 100.00;
        return String.valueOf(df.format(doubleValue));
    }
}
